#include	"dsys.h"

#define		APP_TITLE			"AppDemo"

static T_GUI_HWND hMainWnd;
static int gKeyCode;

void App_Run(void);

T_MODULE
T_WORD WaitPainted(T_GUI_HWND hWnd)
{
	T_GUI_Msg	Msg;
	int			is_painted = 0;

	while (fnGUI_GetMessage(&Msg, hWnd))
	{
		fnGUI_TranslateMessage(&Msg);
		fnGUI_DispatchMessage(&Msg);

		if (is_painted) break;
		if (MSG_PAINT == Msg.message) is_painted = 1;
	}

	return 0;
}

T_MODULE
T_WORD TestWinProc(T_GUI_HWND hWnd, T_WORD message, T_GUI_WPARAM wParam, T_GUI_LPARAM lParam)
{
	T_GUI_HDC hdc;

	switch (message) {
		case MSG_KEYDOWN:
			if (SCANCODE_ENTER == LOUHWORD(wParam)) {
//				fnGUI_PostMessage(hWnd, MSG_APP_LST_CLICK, 0, 0);
			} else if (SCANCODE_ESCAPE == LOUHWORD(wParam)) {
				fnGUI_PostMessage(hWnd, MSG_CLOSE, 0, 0);
			}

			gKeyCode = LOUHWORD(wParam);

			break;

		case MSG_ERASEBKGND:
//			break;
			return 0;

		case MSG_HELP:
			break;

		case MSG_CLOSE:
			fnGUI_DestroyMainWindow(hWnd);
			fnGUI_PostQuitMessage(hWnd);
			return 0;
	}	

	return fnGUI_DefaultMainWinProc(hWnd, message, wParam, lParam);
}

T_MODULE T_VOID InitCreateInfo(T_GUI_pMainWinCreate pCreateInfo)
{
	pCreateInfo->dwStyle        = WS_VISIBLE | WS_CAPTION;
	pCreateInfo->dwExStyle      = WS_EX_NONE;
	pCreateInfo->spCaption      = APP_TITLE;
	pCreateInfo->hMenu          = 0;
	pCreateInfo->hIcon          = 0;
	pCreateInfo->MainWindowProc = TestWinProc;
	pCreateInfo->lx             = 0;
	pCreateInfo->ty             = 0;
	pCreateInfo->rx             = 320;
	pCreateInfo->by             = 240;
	pCreateInfo->iBkColor       = COLOR_LIGHTWHITE;
	pCreateInfo->dwAddData      = 0;
	pCreateInfo->hHosting       = HWND_DESKTOP;
}

T_WORD App_ProcMsg(void)
{
	T_WORD ret;
	T_GUI_Msg Msg;

	if (fnGUI_HavePendingMessage) {
		ret = fnGUI_GetMessage(&Msg, hMainWnd);
		fnGUI_TranslateMessage(&Msg);
		fnGUI_DispatchMessage(&Msg);
	} else {
		ret = 1;
	}

	return ret;
}

T_WORD App_Main(void)
{
	T_GUI_MainWinCreate CreateInfo;

//	fnGUI_EnableStandBy(0);

	InitCreateInfo(&CreateInfo);

	hMainWnd = fnGUI_CreateMainWindow(&CreateInfo);

	WaitPainted(hMainWnd);

	gKeyCode = 0;

	App_Run();

	fnGUI_ThrowAwayMessages(hMainWnd);
	fnGUI_MainWindowCleanup(hMainWnd);

//	fnGUI_EnableStandBy(1);

	return 0;
}

//==============================================================================

#define SCR_WIDTH  240
#define SCR_HEIGHT 160
#define SCR_PITCH  (SCR_WIDTH * 2 / 8)
#define VIDEO_BASE 0x3C0000

void ClearScreen(void)
{
	int cnt;
	volatile int* p;

	p = (volatile int*)VIDEO_BASE;
	cnt = SCR_WIDTH * SCR_HEIGHT / 4 / 4; // 2bpp

	while (cnt--) *p++ = -1;
}

extern const unsigned char VGA_Font_8x16[4096];

static const unsigned char Font_1bit_to_2bits[16] =
{
	0xFF, 0xFC, 0xF3, 0xF0,
	0xCF, 0xCC, 0xC3, 0xC0,
	0x3F, 0x3C, 0x33, 0x30,
	0x0F, 0x0C, 0x03, 0x00,
};

void TextOut(int x, int y, const char* str)
{
	x /= 8; // 8 pixels aligned

	while (*str) {
		int ch;
		const unsigned char* src;

		int i;
		volatile unsigned char* p;

		ch = *str++;
		src = VGA_Font_8x16 + ch * 16; // 16 bytes per character

		p = (volatile unsigned char*)VIDEO_BASE + y * SCR_PITCH + x * 2;

		for (i = 0; i < 16; i++) {
			unsigned char bitmap = *src++;

			p[i * SCR_PITCH + 0] = Font_1bit_to_2bits[bitmap >> 4];
			p[i * SCR_PITCH + 1] = Font_1bit_to_2bits[bitmap & 15];
		}

		x++;
		if (x >= SCR_WIDTH / 8) {
			x = 0;
			y += 16;
		}
	}
}

int GetChar(void)
{
	int r;

	r = gKeyCode;

	gKeyCode = 0;

	return r;
}

//==============================================================================

void App_Run(void)
{
	ClearScreen();

	TextOut(0, 0, "Hello world.");

	for (;;) {
		int ch;

		if (0 == App_ProcMsg())
			break;

		ch = GetChar();
		switch (ch) {
			case 0:
			default:
				break;

			case SCANCODE_A:
				TextOut(0, 32, "A");
				break;

			case SCANCODE_B:
				TextOut(0, 32, "B");
				break;

			case SCANCODE_C:
				TextOut(0, 32, "C");
				break;

			case SCANCODE_D:
				TextOut(0, 32, "D");
				break;
		}
	}
}
